package simco.framework.gui.services;

import simco.framework.gui.graph.ConnectingLine;
import simco.framework.gui.graph.base.GraphObject;
import simco.framework.gui.layout.algorithm.LayoutAlgorithm;
import simco.framework.gui.layout.algorithm.ResultsRatingAlgorithm;
import simco.framework.gui.layout.primitive.LayoutCommand;
import simco.framework.gui.layout.primitive.LayoutNode;
import simco.framework.gui.services.data.GraphModel;

/**
 * Tato trida zajistuje rozmistovani grafickych objektu na
 * platne (grafu simulovanych komponent) pomoci nastaveneho
 * rozmistovaciho algoritmu {@link LayoutAlgorithm}. Vysledky
 * rozmisteni grafu hodnoti podle nastaveneho hodnoticiho
 * algoritmu {@link ResultsRatingAlgorithm}.
 * 
 * @author Matej Prokop, mythge@students.zcu.cz
 */
public class LayoutAgent 
{	
	//injected by Spring DM
	/**
	 * Algoritmus hodnotici rozmisteni grafu   
	 */
	private ResultsRatingAlgorithm ratingAlg;
	
	//injected by Spring DM	
	/**
	 * Algoritmu rozmistujici graf na platne
	 */
	private LayoutAlgorithm layoutAlg;
		
	/**
	 * Provede nekolik pokusu o rozmisteni grafu na platne. Kazdy pokus
	 * ohodnoti nastavenym algoritmem pro hodnoceni grafu. Ze vsech
	 * provedenych pokusu pak vybere rozmisteni, jenz dostalo od
	 * hodnoticiho algoritmu nejlepsi hodnoceni.
	 * 
	 * @param model datovy model grafu komponent
	 * @param attempsCount pocet pokusu o rozmisteni
	 * @return datovy model grafu s nejlepsim dosazenym rozmistenim komponent
	 */
	public GraphModel layoutObject(GraphModel model, int attempsCount)
	{
		LayoutCommand commandObject = new LayoutCommand(model);
		
		for(int i = 0; i < attempsCount; i++)
		{
			layoutAlg.lyoutObjects(commandObject);
			
			int currentRating = ratingAlg.rateResults(commandObject);	
			
            // porovna aktualni reseni s doposud nejlepsim
            if(currentRating < commandObject.getBestRating())
            {
                // ulozi aktulni reseni jako doposud nejlepsi
                commandObject.setBestRating(currentRating);
                for(GraphObject go : commandObject.getLayoutedObjects())
                {
                    commandObject.getBestOption().get(go.getId()).setX(go.getX());
                    commandObject.getBestOption().get(go.getId()).setY(go.getY());
                }
                
                // graf neobsahuje jiz zadne krizeni
                if(commandObject.getBestRating() == 0) break;
            }
		}
		
		for(GraphObject go : model.getGraphObjects() )
		{
			LayoutNode ln = commandObject.getBestOption().get(go.getId());
			go.setPosition( ln.getX(), ln.getY() );
			go.setVisibility(true);
		}
				
        for( ConnectingLine cl : model.getConnLines() )
        {
            cl.setVisibility(true);
        }
        
        return model;
	}

	/**
	 * Nastavi hodnotici algoritmu pro hodnoceni rozmisteni grafu
	 * @param ratingAlg hodnotici algoritmu pro hodnoceni rozmisteni grafu
	 */
	public void setRatingAlg(ResultsRatingAlgorithm ratingAlg) 
	{
		this.ratingAlg = ratingAlg;
	}

	/**
	 * Nastavi rozmistovaci algoritmu pro rozmisteni grafu
	 * @param layoutAlg rozmistovaci algoritmu pro rozmisteni grafu
	 */
	public void setLayoutAlg(LayoutAlgorithm layoutAlg) {
		this.layoutAlg = layoutAlg;
	}
	
	
}
